package com.followmeandroid;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.followmeandroid.enums.ServiceUrl;
import com.followmeandroid.models.CurrentMember;
import com.followmeandroid.models.Member;
import com.followmeandroid.models.SingleToken;
import com.followmeandroid.models.Token;
import com.followmeandroid.util.FollowMeSharedPreferences;
import com.followmeandroid.util.JSONHttpClient;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>Title: LoginActivity</p>
 * <p>Description: This activity controls the content and
 * functionality of the Login screen.</p>
 * @team Adam Drews
 * @email adam.drews@my.uwrf.edu
 * @team Tyler Johnson
 * @email tyler.johnson@my.uwrf.edu
 * @team Nicholas Thorp
 * @email nicholas.thorp@my.uwrf.edu
 * @date 11/17/2014
 */
public class LoginActivity extends Activity {

    private EditText etUserName, etPassword;
    private Button btnLogin;
    private Button btnRegister;
    private Context context;

    /**
     * Creates the layout for the current view. It is passed a
     * bundle of data from the previous activity.
     * @param savedInstanceState    The state of the previous activity.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        context = this;

        //bypass login screen if saved prefs
        try {
            //init the shared preferences -> this must be done from an activity.  This screen is ALWAYS loaded first, it must init it.
            //shared preferences are a singleton by themselves, there is no reason to init more than once.
            FollowMeSharedPreferences.init(this);

            //load current token, user
            Token tok = FollowMeSharedPreferences.loadToken();
            Member savedMember = FollowMeSharedPreferences.loadMember();

            //ensure the member was loaded into current member
            savedMember = CurrentMember.getMember();
            if (savedMember != null && tok.getValid()) {

                //if the token, user is valid, go to the main activity
                final Intent i = new Intent(LoginActivity.this, MainActivity.class);
                i.putExtra("username", tok.getUserName());
                startActivity(i);

                //we are done here, finalize this activity
                finish();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        // No saved prefs, or error, so initialize  the layout components
        etUserName = (EditText) findViewById(R.id.et_username_login);
        etUserName.setSingleLine(true);
        etPassword = (EditText) findViewById(R.id.et_password_login);
        etPassword.setSingleLine(true);
        etPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);

        btnLogin = (Button) findViewById(R.id.btn_Login);
        btnRegister = (Button) findViewById(R.id.btn_register);

        //If the user just registered, get the username from the registration screen if it exists.
        Intent intent = getIntent();
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            etUserName.setText(bundle.get("username").toString());
            etPassword.requestFocus();
        }


        btnLogin.setOnClickListener(logonButtonListener);
        btnRegister.setOnClickListener(registerButtonListener);
    }

    private View.OnClickListener logonButtonListener = new View.OnClickListener() {
        /**
         * Attempts to login when the user hits the login button, passing the
         * username and password.
         * @param v     The current view.
         */
        @Override
        public void onClick(View v) {
            // Execute the AsyncLogin class.  First create, then pass in the current context so we can access shared preferences, etc.  Finally, run async thread
            login(etUserName.getText().toString(),etPassword.getText().toString());
        }
    };

    private View.OnClickListener registerButtonListener = new View.OnClickListener() {
        /**
         * Launches the register activity when clicked.
         * @param v     The current view.
         */
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(getApplicationContext(), RegisterActivity.class);
            startActivity(intent);
        }
    };

    /**
     * Creates the options menu.
     * @param menu      The menu to display.
     * @return true     Success!
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.login, menu);
        return true;
    }

    /**
     * Controls what actions to take when an option in the options
     * menu is clicked.
     * @param item          The item that was selected.
     * @return  true        Success!
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(this);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * The main activity. This method attempts to log the user
     * into the server.
     * @param username      The username to be submitted.
     * @param password      The password to be submitted.
     */
    public void login(String username, String password) {
        final Context context = this.context;

        new AsyncTask<String, JSONObject, Boolean>() {
            Token tokenAuth = null;

            /**
             * The operation to be performed by the thread in the background.
             * @param params Username=[0] and Password=[1]
             * @return boolean of if successful
             */
            @Override
            protected Boolean doInBackground(String... params) {

                JSONHttpClient api = new JSONHttpClient();
                try {
                    // Call the User Authentication Method in API
                    tokenAuth = api.Login(ServiceUrl.GET_LOGIN.toString(), params[0], params[1]);

                    if (tokenAuth == null || !tokenAuth.getValid())
                        return false;

                    //set the token singleton
                    SingleToken.setToken(tokenAuth);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    Log.d("AsyncLogin", e.getMessage());
                }

                try {
                    //save the token response to shared prefs.
                    FollowMeSharedPreferences.saveToken();

                    //load the member
                    Member savedMember = FollowMeSharedPreferences.loadMember();
                    Token token = SingleToken.getToken();

                    //make sure load set current member
                    savedMember = CurrentMember.getMember();

                    //if currentmember is null, there is no saved member data, so request a full pull from the server
                    if (savedMember == null) {
                        //get memberId from Token
                        List<NameValuePair> paramsOut = new ArrayList<NameValuePair>();
                        paramsOut.add(new BasicNameValuePair("memberId", token.getMemberId().toString()));//TODO: what of a null token situation?

                        //get member data (all of it) from the server.
                        Member serverMember = api.Get(ServiceUrl.GET_ALL_INFO.toString(), paramsOut, Member.class);

                        if (serverMember != null) {
                            CurrentMember.setMember(serverMember);
                            FollowMeSharedPreferences.saveMember();
                        } else
                            return false;
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    Log.d("AsyncLogin", e.getMessage());
                }

                return tokenAuth == null ? false : tokenAuth.getValid();
            }

            /**
             * Displays a please wait pop up, and disables the login button
             * while the thread executes.
             */
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                Toast.makeText(context, "Please Wait...", Toast.LENGTH_SHORT).show();
                btnLogin.setEnabled(false);
            }

            /**
             * Re-enables the login button, and launches the main activity if the
             * login was successful.
             * @param result boolean of login results
             */
            @Override
            protected void onPostExecute(Boolean result) {
                //result = true == user valid, token received (or saved).
                btnLogin.setEnabled(true);

                if (result) {
                    //start the main activity
                    final Intent i = new Intent(LoginActivity.this, MainActivity.class);
                    startActivity(i);

                    //we are done here!
                    finish();
                } else {
                    Toast.makeText(context, "Not valid username/password ", Toast.LENGTH_SHORT).show();
                }
            }
        }.execute(username, password);
    }
}
